home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_02_01
/
2n01021a
< prev
next >
Wrap
Text File
|
1990-10-10
|
15KB
|
467 lines
Listing 2. Timer Package Source Code.
TITLE TIMER - STARLITE Timer System.
;*** TIMER -- Lightweight Timer Package.
;
;1. Functional Description.
; This module of STARLITE contains all of the code
; necessary to implement the timer object used inside
; the system.
;
; The system is implemented in a very straightforward
; and fast way that also burns system memory pool.
; It is an a priori assumption that these timers almost
; never fire, they are usually set and reset very
; frequently (thousands of times per second).
;
; The basic implementation is that a block of memory
; is allocated at initialization time, and that block
; is used as an array of timer objects. Exported handles
; are offset addresses of the elements (relative to the
; beginning of DOSDATA), since system pool is addressable
; in DOSDATA.
;
; Starts and stops are made very fast (in fact, single
; instructions) while scans through the timer database
; are actually fairly fast (at least, faster than a
; linked list of them), although this is less important
; since the timer database is scanned every 32ms
; (basically, on a timer tick).
;
; Allocations and deallocations also happen to be quick,
; since the allocator just scans the array for a free
; entry, and the deallocator just clears the "in use"
; bit of an entry.
;
;2. Modification History.
; S. E. Jones 90/06/15. Original for 1.0.
;
;3. NOTICE.
; This software is a derivative of the timer code
; that is licensed as a part of General Software's
; STARLITE architecture. The code in this article
; can be freely incorporated into programs without
; licensing STARLITE architecture from General Software.
;
;4. Build Environment.
; MASM 5.10, no special switches.
; Here are some useful macros to define
; procedures and call them. They eliminate
; the need to manually declare EXTRN's.
DefProc MACRO name
PUBLIC name
name PROC NEAR
ENDM
EndProc MACRO name
ret
ASSUME NOTHING
name ENDP
ENDM
Pcall MACRO name
IF2
IFNDEF name
EXTRN name:NEAR
ENDIF
ENDIF
call name
ENDM
longword struc
lo dw ?
hi dw ?
longword ends
; Package constants.
MILLISECONDS_PER_TICK = 55 ; time between ExpireTimer runs.
; Define a timer object.
TIMER struc
timer_timeout dd ? ; absolute time of expiration.
timer_rtn dd ? ; address of routine to execute.
timer_flags dw ? ; conditions on this timer.
timer_context dw ? ; context value passed to routine.
TIMER ends
TIMER_FLAGS_ALLOCATED = 0001h ; timer object is in use.
TIMER_FLAGS_RUNNING = 0002h ; timer is running.
TIMERCODE SEGMENT PARA PUBLIC 'CODE'
TIMERCODE ENDS
CGROUP GROUP TIMERCODE ; add other code segs here.
TIMERDATA SEGMENT PARA PUBLIC 'DATA'
; The following statics are private to the package.
TimeCounter dd ? ; milliseconds since power-on.
MAX_TIMERS = 100 ; number of timers in system.
StaticArray db MAX_TIMERS dup (type TIMER)
TimerArray dw 0 ; offset pointer to timer array.
TIMERDATA ENDS
DGROUP GROUP TIMERDATA ; add other data segs here.
TIMERCODE SEGMENT
;*** InitializeTimerSystem - Initialize the Timer System.
;
; FUNCTIONAL DESCRIPTION.
; This routine is called by the application to
; initialize the timer package.
;
; ENTRY.
; none.
;
; EXIT.
; none.
;
; USES.
; flags.
ASSUME CS:CGROUP, DS:NOTHING, ES:NOTHING, SS:NOTHING
DefProc InitializeTimerSystem
push ax
push bx
push cx
push dx
push si
push di
push ds
mov ax, DGROUP
mov ds, ax ; (DS) = DGROUP.
ASSUME DS:DGROUP
lea di, CGROUP:StaticArray ; (DI) = adr, database.
mov TimerArray, di ; save database address.
; Initialize timer database.
mov cx, MAX_TIMERS ; (CX) = number of entries to reset.
InitializeTimerSystem_Loop:
mov timer_flags.[di], 0 ; reset this timer.
add di, (SIZE TIMER) ; (DI) = FWA, next timer.
loop InitializeTimerSystem_Loop ; do the rest of 'em.
; Reset the current time up-counter.
sub ax, ax
mov TimeCounter.lo, ax
mov TimeCounter.hi, ax
pop ds
ASSUME DS:NOTHING
pop di
pop si
pop dx
pop cx
pop bx
pop ax
EndProc InitializeTimerSystem
;*** ExpireTimers - Fire Any Expired Timers.
;
; FUNCTIONAL DESCRIPTION.
; This routine is called by interrupt 8 to expire
; system timers. Expired timers are called with
; interrupts ENABLED and with a context in (BX).
; All timer routines are called with FAR linkage,
; so they must return with RETF.
;
; ENTRY.
; none.
;
; EXIT.
; none.
;
; USES.
; flags.
ASSUME CS:CGROUP, DS:NOTHING, ES:NOTHING, SS:NOTHING
DefProc ExpireTimers, PUBLIC
push ax
push bx
push cx
push dx
push si
push di
push ds
mov ax, DGROUP
mov ds, ax ; (DS) = DGROUP.
ASSUME DS:DGROUP
cli ; BEGIN CRITICAL SECTION.
add TimeCounter.lo, MILLISECONDS_PER_TICK
adc TimeCounter.hi, 0 ; do 32-bit update.
sti ; END CRITICAL SECTION.
ExpireTimers_Scan:
nop ; widen interrupt window.
nop
nop
mov ax, DGROUP
mov ds, ax ; (DS) = DGROUP.
cli ; BEGIN CRITICAL SECTION.
mov dx, TimeCounter.hi
mov ax, TimeCounter.lo ; (DX:AX) = current time.
mov di, TimerArray ; (DI) = FWA, 1st timer in system.
or di, di ; is there a timer array?
jz ExpireTimers_Exit ; if not.
sub di, (SIZE TIMER) ; backup one for algorithm.
mov cx, MAX_TIMERS ; number of timers in system.
ExpireTimers_Loop:
dec cx ; (CX) = one less timer to go.
jz ExpireTimers_Exit ; if there are no more, we're done.
add di, (SIZE TIMER) ; (DI) = FWA, next timer in system.
test timer_flags.[di], TIMER_FLAGS_ALLOCATED ; is the timer allocated?
jz ExpireTimers_Loop ; if not.
test timer_flags.[di], TIMER_FLAGS_RUNNING ; is the timer running?
jz ExpireTimers_Loop ; if not.
; If the expiration time is greater than or equal to the current time,
; then we call the timer routine and stop the timer.
cmp timer_timeout.hi.[di], dx ; is the timer's time > current time?
ja ExpireTimers_Loop ; if so.
jb ExpireTimers_Expire ; if expired.
; The most significant portions of the times match exactly. Use the
; low-order times to compare.
cmp timer_timeout.lo.[di], ax ; is the timer's time > current time?
ja ExpireTimers_Loop ; if so.
; The timer has expired. Enable interrupts and call the routine.
ExpireTimers_Expire:
and timer_flags.[di], NOT TIMER_FLAGS_RUNNING ; turn off running bit.
mov timer_timeout.hi.[di], -1 ; ext